#include "PreCompiled.h"
#include "Console.h"
#include "Application_App.h"
#include "Document_App.h"
#include "PropertyStandard.h"
#include "DocumentObject.h"
#include "PropertyUnits.h"
#include "PropertyGeo.h"
#include "app/Placement.h"
#include "PropertyFile.h"
#include "GeoFeature.h"
#include "furniture_staff.h"

using namespace App;
using namespace Base;
int Application_App::_argc;
char** Application_App::_argv;

std::map<std::string,std::string> Application_App::mConfig;
Application_App* Application_App::_pcSingleton = NULL;
Application_App::Application_App(void)
:_pActiveDoc(0)
{

	mpcPramManager["System parameter"] = _pcSysParamMngr;

	mpcPramManager["User parameter"] = _pcUserParamMngr;
}

Application_App::~Application_App(void)
{
}
void Application_App::destruct()
{

}
void Application_App::init()
{
   initType();
   initConfig();
   initApplication();
}
Base::ConsoleObserverStd  *Application_App::_pConsoleObserverStd =0;
Base::ConsoleObserverFile *Application_App::_pConsoleObserverFile =0;

void Application_App::initType()
{ 
	Base::Type::init();
	Base::BaseClass::init();
	Base::Persistence::init();

	App ::Property                  ::init();
	App ::PropertyContainer         ::init();
	App ::PropertyLists             ::init();
	App ::PropertyBool              ::init();
	App ::PropertyFloat             ::init();
	App ::PropertyFloatList         ::init();
	App ::PropertyFloatConstraint   ::init();
	App ::PropertyAngle             ::init();
	App ::PropertyDistance          ::init();
	App ::PropertyLength            ::init();
	App ::PropertySpeed             ::init();
	App ::PropertyAcceleration      ::init();
	App ::PropertyInteger           ::init();
	App ::PropertyIntegerConstraint ::init();
	App ::PropertyPercent           ::init();
	App ::PropertyEnumeration       ::init();
	App ::PropertyIntegerList       ::init();
	App ::PropertyString            ::init();
	App ::PropertyFont              ::init();
	App ::PropertyStringList        ::init();
	App ::PropertyLink              ::init();
	App ::PropertyLinkSub           ::init();
	App ::PropertyLinkList          ::init();
	App ::PropertyLinkSubList       ::init();
	App ::PropertyMatrix            ::init();
	App ::PropertyVector            ::init();
	App ::PropertyVectorList        ::init();
	App ::PropertyPlacement         ::init();
	App ::PropertyPlacementLink     ::init();
	App ::PropertyGeometry          ::init();
	App ::PropertyComplexGeoData    ::init();
	App ::PropertyColor             ::init();
	App ::PropertyColorList         ::init();
	App ::PropertyMaterial          ::init();
	App ::PropertyPath              ::init();
	App ::PropertyFile              ::init();
	App ::PropertyFileIncluded      ::init();
	// Document classes
 	App ::DocumentObject            ::init();
  	App ::GeoFeature                ::init();
  	App ::Placement                 ::init();
 
 	Part::furniture_root            ::init();
 	Part::furniture_chair           ::init();


}
void Application_App::initConfig()
{
   mConfig["AppHomePath"] = FindHomePath();

    _pConsoleObserverStd = new ConsoleObserverStd();
   Console().AttachObserver(_pConsoleObserverStd);
   if (mConfig["Verbose"] == "Strict")
	   Console().SetMode(ConsoleSingleton::Verbose);

   if (mConfig["LoggingFile"] == "1") {
	   _pConsoleObserverFile = new ConsoleObserverFile(mConfig["LoggingFileName"].c_str());
	   Console().AttachObserver(_pConsoleObserverFile);
   }
   else
	   _pConsoleObserverFile = 0;

    LoadParameters();

}

void Application_App::LoadParameters()
{
	// create standard parameter sets
	_pcSysParamMngr = new ParameterManager();
	_pcUserParamMngr = new ParameterManager();

	// Init parameter sets ===========================================================
	//
	if (mConfig.find("UserParameter") == mConfig.end())
		mConfig["UserParameter"]   = mConfig["UserAppData"] + "user.cfg";
	if (mConfig.find("SystemParameter") == mConfig.end())
		mConfig["SystemParameter"] = mConfig["UserAppData"] + "system.cfg";


}
void Application_App::initApplication()
{
	Application_App::_pcSingleton = new Application_App();
}

std::string Application_App::FindHomePath()
{
  wchar_t  szFileName [MAX_PATH] ;

    GetModuleFileName(0, szFileName, MAX_PATH-1);

	std::wstring Call(szFileName), TempHomePath;
	std::wstring::size_type pos = Call.find_last_of(PATHSEP);
	TempHomePath.assign(Call,0,pos);
	pos = TempHomePath.find_last_of(PATHSEP);
	TempHomePath.assign(TempHomePath,0,pos+1);

	// switch to posix style
	for (std::wstring::iterator i=TempHomePath.begin();i!=TempHomePath.end();++i) {
		if (*i == '\\')
			*i = '/';
	}

	return ws2s(TempHomePath);
  
}
// --------------------------------------------- [5/17/2013 Administrator]

std::string Application_App::ws2s(const std::wstring& ws)
{
	std::string curLocale = setlocale(LC_ALL, NULL);        // curLocale = "C";
	setlocale(LC_ALL, "chs");
	const wchar_t* _Source = ws.c_str();
	size_t _Dsize = 2 * ws.size() + 1;
	char *_Dest = new char[_Dsize];
	memset(_Dest,0,_Dsize);
	wcstombs(_Dest,_Source,_Dsize);
	std::string result = _Dest;
	delete []_Dest;
	setlocale(LC_ALL, curLocale.c_str());
	return result;
}

std::wstring Application_App::s2ws(const std::string& s)
{
	setlocale(LC_ALL, "chs"); 
	const char* _Source = s.c_str();
	size_t _Dsize = s.size() + 1;
	wchar_t *_Dest = new wchar_t[_Dsize];
	wmemset(_Dest, 0, _Dsize);
	mbstowcs(_Dest,_Source,_Dsize);
	std::wstring result = _Dest;
	delete []_Dest;
	setlocale(LC_ALL, "C");
	return result;
}


// ----------------------------------------------- [5/17/2013 Administrator]


const char* Application_App::GetHomePath()const
{
	return mConfig["AppHomePath"].c_str();
}

Document_App* Application_App::newDocument(const char* Name,const char* UserName)
{
 	if (!Name || Name[0] == '\0')
 		Name = "Unnamed";

	std::auto_ptr<Document_App> newDoc(new Document_App() );

	DocMap[Name] = newDoc.release();
	_pActiveDoc = DocMap[Name];

	_pActiveDoc->signalNewObject.connect(boost::BOOST_BIND(&Application_App::slotNewObject,this,_1));

	signalNewDocument(*_pActiveDoc);

    return _pActiveDoc;
}

void Application_App::slotNewObject(const App::DocumentObject& obj)
{
  this->signalNewObject(obj);
}

void Application_App::closeAllDocuments()
{

}
std::map<std::string, std::string> Application_App::getImportFilters(const char* Type) const
{
	std::map<std::string, std::string> moduleFilter;
	return moduleFilter;
}
/// Return a list of all import filters.
std::map<std::string, std::string> Application_App::getImportFilters(void) const
{
	std::map<std::string, std::string> moduleFilter;
	return moduleFilter;
}
std::map<std::string, std::string> Application_App::getExportFilters(const char* Type) const
{
        std::map<std::string, std::string> moduleFilter;
		    return moduleFilter;
}

std::map<std::string, std::string> Application_App::getExportFilters(void) const
{
	std::map<std::string, std::string> moduleFilter;
	return moduleFilter;
}
ParameterManager *Application_App::_pcSysParamMngr;
ParameterManager *Application_App::_pcUserParamMngr;


ParameterManager &    Application_App::GetSystemParameter(void)
{
      return *_pcSysParamMngr;
}
/// returns the user parameter
ParameterManager &     Application_App::GetUserParameter(void)
{
      return *_pcUserParamMngr;
}

std::vector<Document_App*> Application_App::getDocuments() const
{
	std::vector<Document_App*> list;
	return list;
}
Document_App* Application_App::getDocument(const char *Name) const
{
	std::map<std::string,Document_App*>::const_iterator it = DocMap.find(Name);
	if(it != DocMap.end())
		return it->second;
    return NULL;
}
/// gets the (internal) name of the document
const char * Application_App::getDocumentName(const Document_App* pDocument) const
{
	for (std::map<std::string,Document_App*>::const_iterator it = DocMap.begin(); it != DocMap.end();it++)
	{
		if(it->second == pDocument)
			return it->first.c_str();
	}
    return NULL;
}

Document_App* Application_App::getActiveDocument()
{
	if(_pActiveDoc)
   return _pActiveDoc;

	return NULL;
}

Base::Reference<ParameterGrp>  Application_App::GetParameterGroupByPath(const char* sName)
{
	std::string cName = sName,cTemp;

	std::string::size_type pos = cName.find(':');

	// is there a path seperator ?
	if (pos == std::string::npos) {
		//throw Base::Exception("Application::GetParameterGroupByPath() no parameter set name specified");
	}
	// assigning the parameter set name
	cTemp.assign(cName,0,pos);
	cName.erase(0,pos+1);

	// test if name is valid
	std::map<std::string,ParameterManager *>::iterator It = mpcPramManager.find(cTemp.c_str());
	if (It == mpcPramManager.end())
		int a = 0;//throw Base::Exception("Application::GetParameterGroupByPath() unknown parameter set name specified");

	return It->second->GetGroup(cName.c_str());
}

